package com.mcgrobot.controller.schedule;

import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.quartz.CronExpression;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.mcgrobot.common.Constants;
import com.mcgrobot.controller.base.BaseController;
import com.mcgrobot.entity.common.McgResult;
import com.mcgrobot.plugin.schedule.FlowSchedulerTaskParam;
import com.mcgrobot.plugin.schedule.InitQuartzJob;
import com.mcgrobot.plugin.schedule.STimetask;
import com.mcgrobot.plugin.schedule.ScheduleJob;
import com.mcgrobot.service.STimetaskService;
import com.mcgrobot.util.PageData;

@Controller
@RequestMapping(value = "/schedule")
public class ScheduleManageController extends BaseController {
	private static Logger logger = LoggerFactory.getLogger(ScheduleManageController.class);
	@Autowired
	STimetaskService sTimetaskService;
	@Autowired
	private SchedulerFactoryBean schedulerFactoryBean;

	@RequestMapping(value="/index")
	public ModelAndView index() throws Exception{
		ModelAndView mv = this.getModelAndView();
		mv.setViewName("schedule/index");
		mv.addObject("version", Constants.VERSION);
		return mv;
	}
	
	@RequestMapping(value="/initCreateTaskModal")
	public ModelAndView initCreateTaskModal() throws Exception {
		ModelAndView mv = this.getModelAndView();
        PageData pd = this.getPageData();
        mv.addObject("modalId", pd.get("modalId"));
		mv.setViewName("schedule/initCreateTaskModal");
		return mv;
	}
	
    @RequestMapping(value="getAll", method=RequestMethod.POST)
    @ResponseBody
    public McgResult getAll() {
        
        McgResult mcgResult = new McgResult();
		try {
		/*
			if(StringUtils.isEmpty(name)){}
		 */
			List<STimetask> sTimetaskList = sTimetaskService.queryAll();
			mcgResult.getResultMap().put("dataList", sTimetaskList);
		} catch (Exception e) {
			logger.error("查询调度任务列表失败：", e);
		}
        return mcgResult;
    }
	
    @RequestMapping(value="getTask", method=RequestMethod.POST, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public McgResult getTask(String taskId) {
        
        McgResult mcgResult = new McgResult();
		try {
	        if(StringUtils.isNotEmpty(taskId)) {
	        	STimetask sTimetask = sTimetaskService.selectByPrimaryKey(taskId);
	        	mcgResult.getResultMap().put("sTimetask", sTimetask);
	        }
		} catch (Exception e) {
			mcgResult.setStatusCode(0);
			mcgResult.setStatusMes("获取任务信息失败，请重试！");
			logger.error("根据ID获取调度任务信息失败：", e);
		}
        return mcgResult;
    }
    
    @RequestMapping(value="taskStart", method=RequestMethod.POST, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public McgResult taskStart(@RequestBody STimetask sTimetask) {
        
        McgResult mcgResult = new McgResult();

		try {
			if(StringUtils.isEmpty(sTimetask.getTaskId())){
				mcgResult.setStatusCode(0);
				mcgResult.setStatusMes("执行任务数据丢失，请重试！");
				return mcgResult;
			}
			if ("1".equals(sTimetask.getPlanStatus())) {
				mcgResult.setStatusCode(0);
				mcgResult.setStatusMes("任务已处于启动中，请先停止任务再启动！");
				return mcgResult;
			}
			
			sTimetask.setPlanStatus("1");
			ScheduleJob scheduleJob = new ScheduleJob();
			scheduleJob.setJobId(sTimetask.getTaskId());
			scheduleJob.setJobStatus(sTimetask.getPlanStatus());
			scheduleJob.setJobGroup(sTimetask.getGroupName()); // 任务组
			scheduleJob.setJobName(sTimetask.getName());// 任务名称
			scheduleJob.setIsConcurrent(sTimetask.getIsConcurrent() == 1 ? "1" : "0"); // 运行状态  1:run  0:stop
			scheduleJob.setCronExpression(sTimetask.getCron());
			scheduleJob.setBeanClass(sTimetask.getBeanName());// 一个以所给名字注册的bean的实例
			scheduleJob.setMethodName(sTimetask.getMethodName());
			scheduleJob.setJobData(sTimetask.getJobData()); // 参数
			InitQuartzJob.addJob(scheduleJob);
			sTimetaskService.updateByPrimaryKeySelective(sTimetask);

			mcgResult.getResultMap().put("sTimetask", sTimetask);
		} catch (Exception e) {
			mcgResult.setStatusCode(0);
			mcgResult.setStatusMes("执行任务失败，请重试！");
			logger.error("执行任务失败：", e);
		}
        return mcgResult;
    }    
    
    @RequestMapping(value="taskStop", method=RequestMethod.POST, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public McgResult taskStop(@RequestBody STimetask sTimetask) {
    	McgResult mcgResult = new McgResult();
		if (sTimetask == null) {
			mcgResult.setStatusCode(0);
			mcgResult.setStatusMes("未找到任务相关数据");
			return mcgResult;
		}
		if ("-1".equals(sTimetask.getPlanStatus())) {
			mcgResult.setStatusCode(0);
			mcgResult.setStatusMes("任务已处于未启动状态");
			return mcgResult;
		}
		if ("0".equals(sTimetask.getPlanStatus())) {
			mcgResult.setStatusCode(0);
			mcgResult.setStatusMes("任务已处于已停止状态");
			return mcgResult;
		}
		if("1".equals(sTimetask.getPlanStatus())) {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			JobKey jobKey = JobKey.jobKey(sTimetask.getName(), sTimetask.getGroupName());
			try {
				scheduler.deleteJob(jobKey);
				sTimetask.setPlanStatus("0");
				sTimetaskService.updateByPrimaryKeySelective(sTimetask);
			} catch (SchedulerException e) {
				mcgResult.setStatusCode(0);
				mcgResult.setStatusMes("停止任务失败，请重试");
				logger.error("停止任务失败：", e);
			}
		} else {
			mcgResult.setStatusCode(0);
			mcgResult.setStatusMes("任务处于未知状态，请重试");
			logger.error("任务处于未知状态，状态值为：", sTimetask.getPlanStatus());
		}
		return mcgResult;
    }
    
    @RequestMapping(value="taskDelete", method=RequestMethod.POST, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public McgResult taskDelete(String taskId) {
    	McgResult mcgResult = new McgResult();
		STimetask sTimetask = sTimetaskService.selectByPrimaryKey(taskId);
		if(StringUtils.isEmpty(sTimetask.getName()) || StringUtils.isEmpty(sTimetask.getGroupName()) ) {
			mcgResult.setStatusCode(0);
			mcgResult.setStatusMes("任务名或任务组名为空，请重试！");
			logger.error("任务名或任务组名为空，无法删除！");
			return mcgResult;
		}
		
		if("1".equals(sTimetask.getPlanStatus()) ) {
			mcgResult.setStatusCode(0);
			mcgResult.setStatusMes("任务处理启动中，请先停止任务后，再进行删除！");
			return mcgResult;
		}
		
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		JobKey jobKey = JobKey.jobKey(sTimetask.getName(), sTimetask.getGroupName());
		try {
			scheduler.deleteJob(jobKey);
			sTimetaskService.deleteByPrimaryKey(sTimetask.getTaskId());
		} catch (SchedulerException e) {
			mcgResult.setStatusCode(0);
			mcgResult.setStatusMes("删除调度任务失败，请重试！");
			logger.error("删除调度任务失败：", e);
		}
    	return mcgResult;
    }
	
	@RequestMapping(value = "/taskSave", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
	@ResponseBody
	public McgResult taskSave(@RequestBody STimetask sTimetask) {
		McgResult mcgResult = new McgResult();
		try {
			if (StringUtils.isEmpty(sTimetask.getName())) {
				mcgResult.setStatusCode(0);
				mcgResult.setStatusMes("任务名称不能为空！");
				return mcgResult;
			}
			if (StringUtils.isEmpty(sTimetask.getCron()) ) {
				mcgResult.setStatusCode(0);
				mcgResult.setStatusMes("调度规则不能为空！");
				return mcgResult;
			}
			if(!isValidExpressionStr(sTimetask.getCron()) && !isValidExpression(sTimetask.getCron())) {
				mcgResult.setStatusCode(0);
				mcgResult.setStatusMes("调度规则无效，请重试！");
				return mcgResult;
			}
 
			if(StringUtils.isEmpty(sTimetask.getTaskId())) {
				sTimetask.setTaskId(UUID.randomUUID().toString());
				sTimetask.setGroupName("McgRobot");
				sTimetask.setPlanStatus("-1");
				FlowSchedulerTaskParam flowTaskParam = new FlowSchedulerTaskParam();
				flowTaskParam.setFlowId(sTimetask.getFlowId());
				flowTaskParam.setTaskId(sTimetask.getTaskId());
				sTimetask.setJobData(JSON.toJSONString(flowTaskParam));
				sTimetask.setMethodName("run");
				sTimetask.setBeanName("com.mcgrobot.plugin.schedule.FlowScheduleTask");
			//	record.setCreateUserId(null);
				sTimetask.setCreateDate(new Date());
				int i = sTimetaskService.insertSelective(sTimetask);
				if (i < 1) {
					mcgResult.setStatusCode(0);
					mcgResult.setStatusMes("保存任务调度失败，请重试！");
				}
			//	mcgResult.getResultMap().put("sTimetask", sTimetask);
			} else {
				STimetask lastSTimetask =  sTimetaskService.selectByPrimaryKey(sTimetask.getTaskId());

				if((!lastSTimetask.getCron().equals(sTimetask.getCron()) || !lastSTimetask.getFlowId().equals(sTimetask.getFlowId())) && "1".equals(lastSTimetask.getPlanStatus()) ){
					Scheduler scheduler = schedulerFactoryBean.getScheduler();
					JobKey jobKey = JobKey.jobKey(lastSTimetask.getName(), lastSTimetask.getGroupName());
					scheduler.deleteJob(jobKey);
					
					lastSTimetask.setName(sTimetask.getName());
					lastSTimetask.setCron(sTimetask.getCron());
					lastSTimetask.setFlowId(sTimetask.getFlowId());
					lastSTimetask.setDesccription(sTimetask.getDesccription());
					lastSTimetask.setIsConcurrent(sTimetask.getIsConcurrent());
					FlowSchedulerTaskParam flowTaskParam = new FlowSchedulerTaskParam();
					flowTaskParam.setTaskId(sTimetask.getTaskId());
					flowTaskParam.setFlowId(sTimetask.getFlowId());
					lastSTimetask.setJobData(JSON.toJSONString(flowTaskParam));
					
					ScheduleJob job1 = new ScheduleJob();
					job1.setJobId(lastSTimetask.getTaskId());
					job1.setJobStatus(lastSTimetask.getPlanStatus());
					job1.setJobGroup(lastSTimetask.getGroupName()); // 任务组
					job1.setJobName(lastSTimetask.getName());// 任务名称
					job1.setIsConcurrent(lastSTimetask.getIsConcurrent() == 1 ? "1" : "0");
					job1.setCronExpression(lastSTimetask.getCron());
					job1.setBeanClass(lastSTimetask.getBeanName());// 一个以所给名字注册的bean的实例
					job1.setMethodName(lastSTimetask.getMethodName());
					job1.setJobData(lastSTimetask.getJobData()); 
					
					InitQuartzJob.addJob(job1);
				}
				
				lastSTimetask.setName(sTimetask.getName());
				lastSTimetask.setCron(sTimetask.getCron());
				lastSTimetask.setFlowId(sTimetask.getFlowId());
				FlowSchedulerTaskParam flowTaskParam = new FlowSchedulerTaskParam();
				flowTaskParam.setFlowId(sTimetask.getFlowId());
				lastSTimetask.setJobData(JSON.toJSONString(flowTaskParam)); 
				lastSTimetask.setDesccription(sTimetask.getDesccription());
				lastSTimetask.setIsConcurrent(sTimetask.getIsConcurrent());
				lastSTimetask.setModifyDate(new Date());
				sTimetaskService.updateByPrimaryKeySelective(lastSTimetask);
			}

		} catch (Exception e) {
			mcgResult.setStatusCode(0);
			mcgResult.setStatusMes("调度规则保存失败，请重试！");
			logger.error("调度规则保存失败：", e);
		}
		
		return mcgResult;
	}
 
    public static boolean isValidExpressionStr(String expressionStr){
        if(StringUtils.isBlank(expressionStr)){
            return false;
        }
        return CronExpression.isValidExpression(expressionStr);
    }
	
	private static boolean isValidExpression(final String cronExpression) {
		CronTriggerImpl trigger = new CronTriggerImpl();
		try {
			trigger.setCronExpression(cronExpression);
			Date date = trigger.computeFirstFireTime(null);
			return date != null && date.after(new Date());
		} catch (Exception e) {
			logger.error("任务调度规则格式不正确：", e);
		}
		return false;
	}

/*	
	// 暂停计划
	@RequestMapping(value = "/stopJob", produces = "text/html;charset=UTF-8;")
	@ResponseBody
	public String stopJob(HttpServletRequest request, HttpSession httpSession) {
		String code = "";
		String message = "";
		String data = null;

		String id = request.getParameter("id");
		STimetask sTimetask = sTimetaskService.selectByPrimaryKey(id);
		if (sTimetask == null) {
			code = "404";
			message = "未找到该任务";
			return null;
		}
		if (!"1".equals(sTimetask.getPlanStatus())) {
			code = "1";
			message = "请先加入计划";
			return null;
		}
		if ("0".equals(sTimetask.getPlanStatus())) {
			code = "1";
			message = "该任务已暂停";
			return null;
		}
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		JobKey jobKey = JobKey.jobKey(sTimetask.getName(), sTimetask.getGroupName());
		try {
			scheduler.pauseJob(jobKey);
			sTimetask.setIsConcurrent(0);
			sTimetask.setPlanStatus("0");
			sTimetaskService.updateByPrimaryKeySelective(sTimetask);
			code = "0";
			return null;
		} catch (SchedulerException e1) {
			e1.printStackTrace();
			code = "-1";
			message = "暂停失败";
			return null;
		}
	}
*/	
	
/*	
	// 恢复计划
	@RequestMapping(value = "/resumeJob", produces = "text/html;charset=UTF-8;")
	@ResponseBody
	public String resumeJob(HttpServletRequest request, HttpSession httpSession) {
		String code = "";
		String message = "";
		String data = null;

		String id = request.getParameter("id");
		STimetask sTimetask = sTimetaskService.selectByPrimaryKey(id);
		if (sTimetask == null) {
			code = "404";
			message = "未找到该任务";
			return null;
		}
		if (!"0".equals(sTimetask.getPlanStatus()) ) {
			code = "1";
			message = "请先加入计划";
			return null;
		}
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		JobKey jobKey = JobKey.jobKey(sTimetask.getName(), sTimetask.getGroupName());
		try {
			scheduler.resumeJob(jobKey);
			sTimetask.setIsConcurrent(1);
			sTimetask.setPlanStatus("1");
			sTimetaskService.updateByPrimaryKeySelective(sTimetask);
			code = "0";
			return null;
		} catch (SchedulerException e1) {
			e1.printStackTrace();
			code = "-1";
			message = "恢复失败";
			return null;
		}
	}
*/
	
/*	
	@RequestMapping(value = "/getJob", produces = "text/html;charset=UTF-8;")
	@ResponseBody
	public String getJob(HttpServletRequest request, HttpSession httpSession) throws SchedulerException {
		String code = "";
		String message = "";
		String data = null;

		try {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
			Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
			List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
			for (JobKey jobKey : jobKeys) {
				List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
				for (Trigger trigger : triggers) {
					ScheduleJob job = new ScheduleJob();
					job.setJobId(trigger.getDescription());// description 放的是job的id
					job.setJobName(jobKey.getName());
					job.setJobGroup(jobKey.getGroup());
					job.setDescription("触发器:" + trigger.getKey());
					Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
					job.setJobStatus(triggerState.name());
					if (trigger instanceof CronTrigger) {
						CronTrigger cronTrigger = (CronTrigger) trigger;
						String cronExpression = cronTrigger.getCronExpression();
						job.setCronExpression(cronExpression);
					}
					jobList.add(job);
				}
			}

			if (jobList.size() == 0) {
				data = "";
			} else {
				// data = ObjToJson.JSONPut(jobList).toJSONString();
			}
			code = "0";
			return null;
		} catch (Exception e) {
			code = "-1";
			message = "系统异常";
			return null;
		}
	}
	*/
}
